package com.auction.common.token;


import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class TokenTemplate {

    TokenProperties tokenProperties;

    public TokenTemplate(TokenProperties tokenProperties) {
        this.tokenProperties = tokenProperties;
    }


    /**
     * 获取token
     * @return
     */
    public String getToken(Map payload) {
        String token = JWT.create()
                .withHeader(getHeader()) //头部
                .withPayload(payload)   //数据
                .withExpiresAt(getValidDate()) //过期时间
                .sign(Algorithm.HMAC256(tokenProperties.getSecret())); //加密算法
        return token;
    }

    /**
     * token验证
     * @param token
     * @return
     */
    public ValidateBean validToken(String token) {
        if(null == token || "".equals(token)){
            return fail("token不能为空");
        }
        DecodedJWT decodedJWT = null;
        try{
            decodedJWT= JWT.require(Algorithm.HMAC256(tokenProperties.getSecret()))
                    .build()
                    .verify(token);
        } catch (TokenExpiredException e) {
            return timedToken();
        } catch (Exception e) {
            return fail("token无效");
        }
        Map<String , Claim> map = decodedJWT.getClaims();
        return sussess(convertedMap(map));

    }

    /**
     * 刷新token
     * @param token
     * @return
     */
    public String flushedToken(String token) {
        ValidateBean validateBean = validToken(token);
        if(validateBean.getCode()==0){
            return null;
        } else if(validateBean.getCode()==2){
            Map<String,Claim> map = JWT.decode(token).getClaims();
            return getToken(convertedMap(map));
        }
        Map map = validateBean.getData();
        return getToken(map);
    }

    /**
     * 将Map<String,Claim> 转换为Map<String,String>
     * @param map
     * @return
     */
    Map<String,String> convertedMap(Map<String ,Claim> map){
        Map<String, String> res = new HashMap<>();
        map.forEach((k,v)->{
            res.put(k,v.asString());
        });
        return res;
    }
    /**
     * 获取头部信息
     * @return
     */
    private Map getHeader(){
        Map map = new HashMap();
        map.put("typ", "JWT");
        map.put("alg", "HS256");
        return map;
    }

    /**
     * 获取要过期的具体时间
     * @return Date
     */
    Date getValidDate(){
        long time = System.currentTimeMillis()+ tokenProperties.getValidTime();
        return new Date(time);
    }



    /**
     * 验证成功
     * @param map
     * @return
     */
    ValidateBean sussess(Map map){
        return new ValidateBean(1,"验证成功",map);
    }

    /**
     * 验证失败
     * @param msg 失败原因
     * @return
     */
    ValidateBean fail(String msg){
        return new ValidateBean(1,msg,null);
    }
    /**
     * token超时
     * @return
     */
    ValidateBean timedToken(){
        return new ValidateBean(2,"token超时",null);
    }

}
